package com.asuka.eva.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.asuka.eva.bo.DemoAsyncTaskBO;
import com.asuka.eva.dao.basic.TempBDAO;
import com.asuka.eva.entity.TempBDO;
import com.asuka.eva.service.DemoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.SpreadsheetVersion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author ZuoWei Jin, 13504284153
 * @version 1.0
 * @since 2021/10/3 23:05
 */
@Service
@Slf4j
public class DemoServiceImpl implements DemoService {
    @Resource
    DemoAsyncTaskBO demoAsyncTaskBO;

    @Resource
    TempBDAO tempBDAO;

    @Value("${kettleTask.splitIndex:3}")
    private int splitIndex;

    /**
     * 结束索引传入此参数 循环这个集合
     */
    public static final int END_OF_COLLECTION = -1;
    /**
     * 开始索引传入此参数 从第一个元素开始循环
     */
    public static final int BEGIN_OF_COLLECTION = 1;


    @Autowired
    ThreadPoolTaskExecutor commonThreadPoolExecutor;

    public void executeTaskSimple() {
        getAllKtrList().stream()
                .map(ktrFileName ->
                        CompletableFuture.runAsync(() ->
                                executeKettleFile(ktrFileName), commonThreadPoolExecutor))
                .collect(Collectors.toList())
                .forEach(CompletableFuture::join);
        log.info("Completed");
    }

    void executeKettleFile(String ktr) {
        try {
            log.info("Executing kettle file {}", ktr);
            Thread.sleep(Long.parseLong(ktr)*1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private List<String> getAllKtrList() {
        return Lists.newArrayList("5","5","50","10","10");
    }

    public void executeAsyncTest() {
        CompletableFuture<Integer> futureForTask1 = CompletableFuture.supplyAsync(
                () -> {
                    log.info("taskOne start");
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    log.info("taskOne end");
                    return 1;
                }
                , commonThreadPoolExecutor);
        CompletableFuture<Integer> futureForTask2 = CompletableFuture.supplyAsync(
                () -> {
                    log.info("taskTwo start");
                    try {
                        Thread.sleep(15000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    log.info("taskTwo end");
                    return 2;
                }
                , commonThreadPoolExecutor);
        CompletableFuture<Integer> futureForTask3 = CompletableFuture.supplyAsync(
                () -> {
                    log.info("taskThree start");
                    try {
                        Thread.sleep(12000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    log.info("taskThree end");
                    return 3;
                }
                , commonThreadPoolExecutor);
        log.info("等待异步线程执行......");
        CompletableFuture.allOf(futureForTask1, futureForTask2, futureForTask3).join();
        Integer resultOfTask1 = futureForTask1.join();
        Integer resultOfTask2 = futureForTask2.join();
        Integer resultOfTask3 = futureForTask3.join();
        Integer sumResult = resultOfTask1 + resultOfTask2 + resultOfTask3;
        log.info("异步线程执行结束,获取执行结果:任务1={},任务2={},任务3={},执行文件总数={}",
                resultOfTask1, resultOfTask2, resultOfTask3, sumResult);
        // 将生产库数据表的数据量写入到通知表中
        printForEnd();
        log.info("executeKettleFileForTask执行结束");
    }

    public void printForEnd() {
        log.info("开始插入通知信息....");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("插入通知信息结束....");
    }

    public static void resetCellMaxTextLength() {
        SpreadsheetVersion excel2007 = SpreadsheetVersion.EXCEL2007;
        if (Integer.MAX_VALUE != excel2007.getMaxTextLength()) {
            Field field;
            try {
                field = excel2007.getClass().getDeclaredField("_maxTextLength");
                field.setAccessible(true);
                field.set(excel2007, Integer.MAX_VALUE);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private Map<Integer, String> getDefaultMap() {
        Map<Integer, String> defaultMap = new HashMap<>();
        defaultMap.put(1, "1");
        defaultMap.put(2, "2");
        defaultMap.put(3, "3");
        defaultMap.put(4, "4");
        defaultMap.put(5, "5");
        defaultMap.put(6, "6");
        defaultMap.put(7, "7");
        defaultMap.put(8, "8");
        return defaultMap;
    }

    private int executeMap(int startIndex, int endIndex) {
        Map<Integer, String> defaultMap = getDefaultMap();
        int totalFileExecutions = 0;
        int ktrMapSize;
        if (endIndex <= 0 || startIndex > endIndex) {
            ktrMapSize = defaultMap.size();
        } else {
            ktrMapSize = endIndex;
        }
        for (int i = startIndex; i <= ktrMapSize; i++) {
            log.info("输出mapValue={}", defaultMap.get(i));
            totalFileExecutions ++;
        }
        return totalFileExecutions;
    }

    /**
     * 文件下载（失败了会返回一个有部分数据的Excel）
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DownloadData}
     * <p>
     * 2. 设置返回的 参数
     * <p>
     * 3. 直接写，这里注意，finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */
    public void download(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        QueryWrapper<TempBDO> queryWrapper = new QueryWrapper<>();
        Page<TempBDO> page;
        int pageNo = 1;
        page = new Page<>(pageNo, 10000);
        queryWrapper.isNull("status");
        page = tempBDAO.selectPage(page, queryWrapper);
        List<TempBDO> records = page.getRecords();
        List<List<TempBDO>> split = CollUtil.split(records, 1000);
        List<DemoData> printList = new ArrayList<>();
        for (List<TempBDO> tempBDOS : split) {
            List<String> collect = tempBDOS.stream().map(TempBDO::getMatterNo).collect(Collectors.toList());
            Map<String, List<String>> paramMap = new HashMap<>();
            paramMap.put("ids", collect);
            String jsonStr = JSONUtil.toJsonStr(paramMap);
            log.info("PagePrint={}", jsonStr);
            DemoData demoData = new DemoData();
            demoData.setString(jsonStr);
            printList.add(demoData);
        }
        resetCellMaxTextLength();
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(printList);
    }

    @Override
    public void testAsyncTask() {
        QueryWrapper<TempBDO> queryWrapper = new QueryWrapper<>();
        Page<TempBDO> page;
        int pageNo = 1;
        while (true) {
            page = new Page<>(pageNo, 1000);
            queryWrapper.isNull("status");
            page = tempBDAO.selectPage(page, queryWrapper);
            List<TempBDO> records = page.getRecords();
            if (CollUtil.isEmpty(records)) {
                break;
            } else {
                TempBDO tempBDO = new TempBDO();
                tempBDO.setStatus(3);
                for (TempBDO record1 : records) {
                    tempBDO.setId(record1.getId());
                    tempBDAO.updateById(tempBDO);
                }
                pageNo++;
            }
            List<String> collect = records.stream().map(TempBDO::getMatterNo).collect(Collectors.toList());
            Map<String, List<String>> paramMap = new HashMap<>();
            paramMap.put("ids", collect);
            demoAsyncTaskBO.doAsyncTask(paramMap);
//            try {
//                Thread.sleep(10000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
            String jsonStr = JSONUtil.toJsonStr(collect);
            log.info("PagePrint={}", jsonStr);
        }
    }

    public static void main(String[] args) {
        ArrayList<String> yuanshilist = Lists.newArrayList("210221195206160558", "210225196312100620", "210213199109184820", "210219194408124612", "210221201609088114", "210282200705188711", "21021119990227292X", "210221195709280519", "210204201302102640", "210282201006245945", "210213194910295216", "210222194708027513", "210222197211126616", "210211200401228029", "210282200502142318", "220422196505105624", "210283200212095513", "210221197509188717", "210222196508097217", "210282200402252325", "210282199909166316", "210283201005173317", "210221196310280941", "210222195005017815", "210222195401230220", "210213201810023320", "210222196510013123", "210281200109183635", "210282201108281912", "210222194303260915", "210283200508286642", "210204200202115335", "21022119580210056X", "21028120050202362X", "210213200708245213", "430503200202161519", "21021919450115711X", "210213198912191013", "210213200705101011", "210221197401180780", "210283200801294318", "210212200209282048", "210213200811291517", "210283201209131522", "21021320170801302X", "210213200403158522", "210221196808200670", "210221196307230732", "210222197803170215", "210222195411123824", "220223196204072617", "210222198312047217", "210219195512089313", "210283200411201542", "210211200207096763", "21022119651103304X", "210222195201017820", "210222197403236959", "210221194002130598", "21028120080523802X", "210282201603089127", "210204200405297423", "210225197304260426", "210221195802043032", "210282195202155922", "222401200402170035", "210211200306225524", "210213200110022023", "210222196506163823", "210212200205057425", "210222194405150215", "210222195603180217", "210213200306295429", "210282200207135334", "210283200006216011", "21021320161230501X", "210282200310067210", "210213200706103027", "210219194311089320", "210222196910107217", "210213198010265212", "210283201802197020", "210222195310310225", "210213200908174421", "210212200206034938", "210221195307280567", "210219195810319316", "210213199708174421", "210281200309244623", "210213199210254838", "230227197101070135", "210282200411190226", "210213200306225826", "210213200205060516", "210221195112060601", "210213200204265624", "210281201010193627", "210221197103070612", "210219196501107111", "210212200511196925", "210213201012310034", "210213201105293026", "210282200203250917", "210211201010144914", "210221195904240731", "210213200511222528", "210222196710057884", "210212200404270018", "210221197603210634", "210282200610050218", "210281201208128628", "210281200004212014", "210213201102201018", "210222197303048416", "210204200203054837", "210213201307052511", "210282200202135933", "210222195009080248", "210221195203060631", "210281200907034626", "210222196210220614", "210282200212250628", "210224200107251422", "210204200407053529", "210213200702268545", "210281200907137123", "210222196504293819", "210222197005285325", "210204200410016753", "210222198302117269", "21028120070811982X", "210213198004133627", "210211200110296769", "210222196801293823", "210221193312313037", "210213200503270036", "210204200508162193", "210204200006163524", "210282200407276617", "210211200209014514", "210219194901019322", "210222195206153127", "210213200010175823", "210204200204283041", "210211200404130422", "210213200204164612", "210222195904140219", "210219197709033435", "210213200212090529", "210281199111034617", "210282200203182328", "210222195011200229", "210222195002220252", "210213200112235612", "210204200210012627", "210213201609091049", "210281200303274311", "210219196312054815", "210219195301163448", "21021320090816002X", "210213201003180012", "210881200211195969", "210221195610130588", "210222195401272324", "210283200208061513", "210212200209190020", "210204200204133043", "210222195302123112", "210211199912312163", "210211200402267433", "210281196309144615", "210282200907167820", "210221200303037926", "210222194502050945", "21028220001101213X", "210221197602030674", "21021319900304394X", "210221201704298734", "210213196404193013", "230223198101281257", "210213200704210515", "21028220010914531X", "210281200101274647", "210282201007217516", "210221195106230539", "210222197409259115", "210221195902240535", "152122198509071827");
        ArrayList<String> strings = Lists.newArrayList("210221197509188717", "210222196508097217", "210225196312100620", "210213199109184820", "210221195206160558", "21021919450115711X", "210213198912191013", "210213200705101011", "210222197211126616", "210222197803170215", "210222195411123824", "210221196307230732", "210204200405297423", "210225197304260426", "210204200202115335", "210282200502142318", "220422196505105624", "210283201802197020", "210222195401230220", "210213201810023320", "210222194303260915", "210282201108281912", "210283200508286642", "210222197409259115", "210221195902240535", "210221195106230539", "210281200101274647", "210212200404270018", "210213200511222528", "210221197603210634", "210222196710057884", "152122198509071827", "21022119580210056X", "210282200705188711", "210219194408124612", "210221201609088114", "210221197401180780", "210213200704210515", "21028220010914531X", "210213200708245213", "430503200202161519", "210283201209131522", "210281200109183635", "210222196510013123", "210211200401228029", "210213200306295429", "210282200207135334", "210213200706103027", "210282200310067210", "210282201603089127", "210221194002130598", "21028120080523802X", "21021119990227292X", "210221195709280519", "210204201302102640", "210282201006245945", "210219197709033435", "220223196204072617", "210222198312047217", "210219195512089313", "210222196210220614", "210282200212250628", "210222196504293819", "210282200402252325", "210282199909166316", "210281200907137123", "210213199708174421", "210281200309244623", "210213199210254838", "21021320170801302X", "210224200107251422", "210213200702268545", "210204200407053529", "210213194910295216", "21028120050202362X", "210222194708027513", "210219195810319316", "210282201007217516", "210213200908174421", "210222195310310225", "210212200206034938", "210281200004212014", "210213201102201018", "230227197101070135", "210221195307280567", "210283200212095513", "210221197103070612", "210219196501107111", "210212200511196925", "210213201307052511", "210213200204265624", "210213200306225826", "210282200411190226", "210281201010193627", "210221195112060601", "210213200205060516", "210221201704298734", "210204200508162193", "210204200006163524", "210211200209014514", "210282200407276617", "210213200010175823", "210222195206153127", "210222194502050945", "210221200303037926", "210221197602030674", "21028220001101213X", "210211200404130422", "210204200204283041", "210213200204164612", "210222195904140219", "210281196309144615", "210282200907167820", "210213196404193013", "230223198101281257", "21022119651103304X", "210222195201017820", "210222197403236959", "210211200207096763", "21021319900304394X", "21028120070811982X", "210213198004133627", "210211200110296769", "210222197005285325", "210204200410016753", "210222198302117269", "210213200503270036", "210221195203060631", "210281200907034626", "210219194311089320", "210222196910107217", "210213198010265212", "210283200006216011", "21021320161230501X", "210213201003180012", "210881200211195969", "210221195610130588", "210222195401272324", "210211199912312163", "210283200208061513", "210211200402267433", "210283200411201542", "210222196801293823", "210221193312313037", "210219194901019322", "210204200204133043", "210222195302123112", "210213201609091049", "210283200801294318", "210213200811291517", "210212200209282048", "210282200610050218", "210281201208128628", "222401200402170035", "210211200306225524", "210213200110022023", "210222195005017815", "210221196310280941", "210283201005173317", "210212200205057425", "210222194405150215", "210222195603180217", "210222196506163823", "210221195802043032", "210282195202155922", "210221196808200670", "210213200403158522", "210213200112235612", "210204200210012627", "210219196312054815", "210281200303274311", "210219195301163448", "210213200212090529", "210222195002220252", "210222195011200229", "210282200203182328", "210281199111034617", "21021320090816002X", "210212200209190020", "210282200203250917", "210211201010144914", "210221195904240731", "210222197303048416", "210204200203054837", "210213201012310034", "210219194608167318", "210213201105293026", "210222195009080248", "210282200202135933", "210204200108086750");
//        System.out.println(strings1.stream().distinct().count());
        System.out.println(yuanshilist.stream().distinct().count());
        log.info("现在得数据不存在于原始list");
        strings.stream().filter(s -> !yuanshilist.contains(s)).collect(Collectors.toList()).forEach(System.out::println);
        log.info("原始list不存在于现在得数据");
        yuanshilist.stream().filter(s -> !strings.contains(s)).collect(Collectors.toList()).forEach(System.out::println);
    }
}
